<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Services\WoChatService;
use Carbon\Carbon;

class EmploymentContract extends Model
{
	use SoftDeletes;
	protected $fillable = ['creator_id', 'employee_id', 'out_no', 'type', 'status', 'termination_reason', 'work_location', 'position', 'salary_structure', 'sign_at', 'effective_at', 'probation_at', 'expiration_at'];
	protected $casts = [
		'sign_at'  => 'date:Y-m-d',
		'effective_at'  => 'date:Y-m-d',
		'probation_at'  => 'date:Y-m-d',
		'expiration_at'  => 'date:Y-m-d',
		'salary_structure'  => 'object'
	];

	// 类型
	public static $typeMap = [
		1 => '固定期限',
		2 => '无固定期限',
		3 => '实习协议',
		4 => '劳务派遣',
		5 => '非全日制'
	];
	// 状态
	public static $statusMap = [
		1 => '生效中',
		2 => '已到期',
		3 => '提前终止',
		4 => '续签待确认'
	];

	protected static function boot()
	{
		parent::boot();
		static::creating(function ($m) {
			if (!$m->no) {
				$m->no = static::findAvailableNo();
				if (!$m->no) return false;
			}
		});
	}

	public function creator()
	{
		return $this->belongsTo(Employee::class);
	}

	public function employee()
	{
		return $this->belongsTo(Employee::class);
	}

	public function attachments()
	{
		return $this->morphMany(ObjectStorage::class, 'common')->orderByDesc('created_at');
	}

	public function scopeWhichKeyword($q, $k)
	{
		if (!$k) return $q;
		return $q->where(self::qualifyColumn('no'), 'like', "%{$k}%")
				->orWhere(self::qualifyColumn('out_no'), 'like', "%{$k}%")
				->orWhere(self::qualifyColumn('position'), 'like', "%{$k}%")
				->orWhere(self::qualifyColumn('work_location'), 'like', "%{$k}%")
				->orWhere(self::qualifyColumn('termination_reason'), 'like', "%{$k}%");
	}

	public function scopeWhichType($q, $s)
	{
		return $q->when($s, function ($q, $s) {
			$current = now();
			if (!is_array($s)) {
				$s = [$s];
			}
			$q->whereIn(self::qualifyColumn('type'), $s);
		});
	}

	public function scopeWhichStatus($q, $s)
	{
		return $q->when($s, function ($q, $s) {
			$current = now();
			if (!is_array($s)) {
				$s = [$s];
			}
			$q->whereIn(self::qualifyColumn('status'), $s);
		});
	}

	public function scopeWhichAt($c, $a, $d)
	{
		$at = "{$a}_at";
		if (! in_array($at, ['sign_at', 'effective_at', 'probation_at', 'expiration_at'])) return $c;
		$field = self::getTable().".{$at}";
		if (! is_array($d)) return $c->orderByDesc($field);
		if ($d[0]) $c->where($field, '>=', $d[0]);
		if ($d[1]) $c->where($field, '<=', $d[1]);
	}

	public function scopeWhichEmployee($q, $s, $u = 0)
	{
		return $q->when($s, function ($q, $s) use($u) {
			if (!is_array($s)) {
				$s = [$s];
			}
			$q->whereIn(self::qualifyColumn('employee_id'), $s);
			if ($u) {
				foreach ($s as $i) {
					DB::table('search_weights')->updateOrInsert(['user_id' => $u, 'employee_id' => $i]);
				}
				DB::table('search_weights')->where('user_id', $u)->whereIn('employee_id', $s)->increment('total');
			}
		});
	}

	public static function beAboutToExpire($days = 45)
	{
        $now = Carbon::now();
        // 查询未签用工合同
        $contracts = EmploymentContract::select('employment_contracts.*')
                    ->rightJoinSub(EmploymentContract::selectRaw('employee_id, MAX(created_at) AS at')->groupBy('employee_id'), 'lsat', function ($join) {
                        $join->on('employment_contracts.employee_id', 'lsat.employee_id')->on('employment_contracts.created_at', 'lsat.at');
                    });
        $enrollments = Enrollment::select('enrollments.*')
                    ->rightJoinSub(Enrollment::selectRaw('employee_id, MAX(created_at) AS at')->groupBy('employee_id'), 'lsat', function ($join) {
                        $join->on('enrollments.employee_id', 'lsat.employee_id')->on('enrollments.created_at', 'lsat.at');
                    });
        $shops = [];
        $employees = Employee::select('employees.name', 'enrollment.type', 'employees.shop_id')
            ->leftJoinSub($enrollments, 'enrollment', function ($join) {
                $join->on('employees.id', 'enrollment.employee_id');
            })
            ->leftJoinSub($contracts, 'contract', function ($join) {
                $join->on('employees.id', 'contract.employee_id');
            })
            ->whereNotNull('enrollment.id')
            ->whereNull('employees.separated_at')
            ->whereNull('contract.id')
            ->get()
            ->groupBy('shop_id');
        foreach ($employees as $shop_id => $employees) {
        	$shops[$shop_id]['unsigned'] = $employees;
        }
		// 查询已过期或即将过期
		$employment_contracts = self::select('employment_contracts.no', 'employment_contracts.type', 'employment_contracts.status', 'employment_contracts.expiration_at', 'employees.name', 'employees.shop_id')
			->join('employees', 'employees.id', 'employment_contracts.employee_id')
			->whereIn('employment_contracts.status', [1, 2])
			->get();
		$employment_contracts = $employment_contracts->groupBy('shop_id');
        foreach ($employment_contracts as $shop_id => $contracts) {
        	$shops[$shop_id]['expire'] = $contracts->where('status', 1)->where('expiration_at', '>', $now->format('Y-m-d'))->where('expiration_at', '<', $now->copy()->addDays($days)->format('Y-m-d'));
        	$shops[$shop_id]['expired'] = $contracts->where('status', 2);
        }
		foreach ($shops as $shop_id => $sshop) {
			$shop = Shop::find($shop_id);
			$oa = $shop->oaInfo();
			if ($oa['code'] == 0) {
				$content = "";
				if (isset($sshop['unsigned']) && count($sshop['unsigned'])) {
					$content .= "` 未签约 ".count($sshop['unsigned'])." 人 `\n";
					foreach ($sshop['unsigned']->groupBy('type') as $t => $unsigned) {
						$name = [];
						foreach ($unsigned as $un) {
							array_push($name, "{$un->name}");
						}
						if (!empty($name)) {
							$type = isset(Enrollment::$typeMap[$t]) ? Enrollment::$typeMap[$t] : '未知类型';
							$content .= ">**{$type}**：<font color=\"comment\">".implode('、', $name)."</font>\n";
						}
					}
					$content .= "\n";
				}
				if (isset($sshop['expire']) && count($sshop['expire'])) {
					$content .= "` {$days} 天内即将过期 ".count($sshop['expire'])." 份 `\n";
					foreach ($sshop['expire']->groupBy('type') as $t => $expire) {
						$name = [];
						foreach ($expire as $un) {
							array_push($name, "{$un->no}@{$un->name}");
						}
						if (!empty($name)) {
							$type = isset(self::$typeMap[$t]) ? self::$typeMap[$t] : '未知类型';
							$content .= ">**{$type}**：<font color=\"comment\">".implode('、', $name)."</font>\n";
						}
					}
					$content .= "\n";
				}
				if (isset($sshop['expired']) && count($sshop['expired'])) {
					$content .= "` 已过期 ".count($sshop['expired'])." 份 `\n";
					foreach ($sshop['expired']->groupBy('type') as $t => $expired) {
						$name = [];
						foreach ($expired as $un) {
							array_push($name, "{$un->no}@{$un->name}");
						}
						if (!empty($name)) {
							$type = isset(self::$typeMap[$t]) ? self::$typeMap[$t] : '未知类型';
							$content .= ">**{$type}**：<font color=\"comment\">".implode('、', $name)."</font>\n";
						}
					}
					$content .= "\n";
				}
		// 		// 查找有创建合同权限人员通知
				$users = WochatUser::select('wochat_users.userid')
					->join('employees', 'employees.id', 'wochat_users.employee_id')
					->join('employee_role_relation as e_r', 'e_r.employee_id', '=', 'employees.id')
					->join('role_permission_relation as r_p', 'e_r.role_id', '=', 'r_p.role_id')
					->join('permissions', 'r_p.permission_id', '=', 'permissions.id')
					->where('employees.shop_id', $shop_id)
					->where('permissions.action', 'create')
					->where('permissions.api', 'employees/contracts')
					->get();
				if ($content) {
					switch ($oa['type']) {
						case 'wochat':
							$wo_ser = new WoChatService();
							$wo_ser->sendMsg($oa['appid'], $oa['secret'], [
								// "touser" => 'woHUXCSwAAS21e1KRyt577HhKCEYgKOw',
								"touser" => $users->implode('userid', '|'),
								"agentid" => $oa['agentid'],
								"msgtype" => 'markdown',
								"markdown" => [
									"content" => "### 企业用工风险提醒：<font color=\"warning\">极高</font>\n{$content}请相关负责人及时处理，降低用工风险！"
								]
							]);
							break;
					}
				}
			}
		}
	}

	public static function findAvailableNo()
	{
		$prefix = 'EC'.date('Ymd');
		$num = static::query()->whereDate('created_at', date('Y-m-d'))->count();
		$no = $prefix.str_pad($num + 1, 3, '0', STR_PAD_LEFT);
		if (!static::query()->whereNo($no)->exists()) return $no;
		return static::findAvailableNo();
	}
}
